﻿#include"XQHttpRequestAccount.h"
#include"XQHttpClient.h"
#include"XQHttpHeadRequest.h"
#include"XQUserInfo.h"
#include"XQAlgorithm.h"
#include"XQLog.hpp"
#include<QJsonArray>
#include<QEventLoop>
#include<QTimer>
using namespace HttpAccount;
using Debug = Http::Debug;
XQHttpRequestAccount::XQHttpRequestAccount(QObject* parent)
	:XQHttpRequestObject(parent)
{
	init();
}

XQHttpRequestAccount::~XQHttpRequestAccount()
{
}

Error XQHttpRequestAccount::error()const
{
	return m_error;
}

HttpAccount::Result XQHttpRequestAccount::result() const
{
	return m_result;
}

const XQAccountData& XQHttpRequestAccount::accountData() const
{
	return m_account;
}

bool XQHttpRequestAccount::isLogin() const
{
	return m_Login;
}

void XQHttpRequestAccount::setHttp(XQHttpClient* http)
{
	XQHttpRequestObject::setHttp(http);
	if(http)
		connect(m_http, &XQHttpClient::disconnected, [this] {m_requestCount = 0; m_Login = false; emit exit(); });
}

void XQHttpRequestAccount::connectToServer(const QString& url)
{
	m_http->connectToServer(url);
}

bool XQHttpRequestAccount::connectToServerWait(const QString& url, int msecs)
{
	return m_http->connectToServerWait(url,msecs);
}

bool XQHttpRequestAccount::wait(int msecs)
{
	if (m_http == nullptr || !m_http->isConnected())
		return false;

	QDateTime start = QDateTime::currentDateTime();
	QEventLoop loop;
	//connect(this,&XQHttpRequestAccount::errorOccurred,&loop, &QEventLoop::quit);
	connect(this, &XQHttpRequestAccount::done, &loop, &QEventLoop::quit);
	if(msecs>0)
		QTimer::singleShot(msecs, &loop, &QEventLoop::quit);
	loop.exec();
	if (start.addMSecs(msecs) <= QDateTime::currentDateTime())
		return false;
	return true;

}

void XQHttpRequestAccount::Account_Login(const QString& account, const QString& password)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::Login);
	QVariantMap map;
	account_encrypt(map, account);
	password_encrypt(map, password);
	auto json = variantMap_toJson(map);
	send(json);
	if(isDebugModel(Debug::HeadRequest))
	{
		XQLog(logName()) << "发送登录请求\r\n" << m_http->request()->header_toString() << "\r\n" << QString(json);
	}

	/*if (!m_http->wait_Reply())
		emit errorOccurred(Error::Timeout);
	auto data = m_http->toByteArray();*/

}

void XQHttpRequestAccount::Account_Logout()
{
	if (!isConnected())
	{
		emit errorOccurred(Error::NotLogin);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::Logout);
	send();
}

void XQHttpRequestAccount::Account_Register(const XQAccountData& account, const QString& verify)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::Register);
	auto map=account.toVariantMap(true);
	map["verify"] = verify;
	account_encrypt(map,account.account);
	password_encrypt(map, account.password);
	if(map.contains("portrait_data"))
	send(variantMap_toJson(map));
}

void XQHttpRequestAccount::Account_ModifyPassword(const QString& account, const QString& password, const QString& newPassword)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::ModifyPassword);
	QVariantMap map;
	account_encrypt(map, account);
	password_encrypt(map, password);
	newPassword_encrypt(map, newPassword);
	auto json = variantMap_toJson(map);
	send(json);
}

void XQHttpRequestAccount::Account_ModifyInfo(const XQAccountData& account, const QStringList& fields)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::ModifyInfo);
	auto f = fields;
	if (f.isEmpty())
	{
		f = XQAccountData::Fields();
	}
	else
	{
		if (!f.contains("account"))
			f << "account";
		if (!f.contains("password"))
			f << "password";
	}
	auto map = account.toVariantMap(true, f);
	account_encrypt(map,account.account);
	password_encrypt(map, account.password);

	send(variantMap_toJson(map));
}

void XQHttpRequestAccount::Account_ModifyEmail(const QString& email, const QString& verify, const QString& newEmail, const QString& newVerify)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::ModifyEmail);
	QVariantMap map = {
		{"email",email},
		{"verify",verify},
		{"newEmail",newEmail},
		{"newVerify",newVerify},
	};

	send(variantMap_toJson(map));
}
void XQHttpRequestAccount::Account_ModifyEmail(const QString& account, const QString& password, const QString& email, const QString& verify, const QString& newEmail, const QString& newVerify)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::ModifyEmail);
	QVariantMap map = {
		{"email",email},
		{"verify",verify},
		{"newEmail",newEmail},
		{"newVerify",newVerify},
	};
	account_encrypt(map,account);
	password_encrypt(map,password);
	send(variantMap_toJson(map));
}

void XQHttpRequestAccount::Account_portrait(const QString& account)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::Portrait);
	QVariantMap map;
	account_encrypt(map, account);
	send(variantMap_toJson(map));
}

void XQHttpRequestAccount::Account_NewEmailVerify(const QString& email)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::NewEmailVerify);
	auto json = variantMap_toJson({
		{"email",email.toUtf8()}
		});
	if (isDebugModel(Debug::HeadRequest))
	{
		XQLog(logName()) << "发送验证码请求\r\n" << m_http->request()->header_toString() << "\r\n" << QString(json);
	}
	send(json);
}
void XQHttpRequestAccount::Account_BindEmailVerify(const QString& account, const QString& email)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::BindEmailVerify);
	QVariantMap map = {
		{"email",email}
	};
	account_encrypt(map,account);
	auto json = variantMap_toJson(map);
	if (isDebugModel(Debug::HeadRequest))
	{
		XQLog(logName())<<account << ":发送验证码请求\r\n" << m_http->request()->header_toString() << "\r\n" << QString(json);
	}
	send(json);
}
void XQHttpRequestAccount::Account_Info(const QStringList& fields)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::Info);
	auto f = fields;
	if (f.isEmpty())
		f = XQAccountData::Fields();
	QJsonObject object;
	object.insert("fields", QJsonArray::fromStringList(f));
	auto json=QJsonDocument(object).toJson();
	send(json);
}

void XQHttpRequestAccount::Account_Info(const QString& account, const QString& password, const QStringList& fields)
{
	if (!isConnected() && !m_http->connectToServerWait())
	{
		emit errorOccurred(Error::ServerError);
		return;
	}
	m_http->request()->setHeader(Head::Type, Head::Info);
	auto f = fields;
	if (f.isEmpty())
		f = XQAccountData::Fields();
	QVariantMap map;
	map["fields"] = f;
	//object.insert("fields", QJsonArray::fromStringList(f));
	account_encrypt(map,account);
	password_encrypt(map, password);
	send(variantMap_toJson(map));
}

void XQHttpRequestAccount::init()
{
	/*m_http = new XQHttpClient(NetworkType::Tcp,this);
	connect(m_http,&XQHttpClient::connected,this,&XQHttpRequestAccount::connected);
	connect(m_http, &XQHttpClient::headReplyRead,this,&XQHttpRequestAccount::replyRead);
	m_http->request()->setHeader(Head::App, name().toUtf8());*/
	
}

void XQHttpRequestAccount::httpClient_init()
{
	XQHttpRequestObject::httpClient_init();
	m_http->request()->setHeader(Head::App, name().toUtf8());
}

void XQHttpRequestAccount::send(const QByteArray& data)
{
	++m_requestCount;
	m_http->request()->setHeader(Head::App, name().toUtf8());
	m_http->request()->setHeader(Head::Command, Head::Account);
	m_http->post(data);
}

void XQHttpRequestAccount::account_encrypt(QVariantMap& map, const QString& account)
{
	map["account"] = account.toUtf8().toBase64();
}

void XQHttpRequestAccount::password_encrypt(QVariantMap& map, const QString& password)
{
	map["password"]= password.toUtf8().toBase64();
}

void XQHttpRequestAccount::newPassword_encrypt(QVariantMap& map, const QString& newPassword)
{
	map["newPassword"] = newPassword.toUtf8().toBase64();
}

void XQHttpRequestAccount::resultProcessing(Result result)
{
	//auto data = QByteArray::fromBase64(m_http->toByteArray());
	auto json=QJsonDocument::fromJson(m_http->toByteArray()).object();
	switch (result)
	{
	case Result::null:
		break;
	case Result::AccountLogin:m_Login = true; emit login();
		break;
	case Result::AccountLogout:m_Login = false; emit exit();
		break;
	case Result::AccountInfo:m_account.setDatas(json.toVariantMap(),true);
		break;
	case Result::AccountPortrait:m_account.setDatas(json.toVariantMap(), true);
		break;
	default:
		break;
	}
	m_result = result;
	emit this->resultOccurred(result);
}

void XQHttpRequestAccount::replyRead(const XQHttpHeadReply& reply)
{
	if (isDebugModel(Debug::HeadReply))
	{
		XQLog(logName()) << "服务器回复\r\n" << reply.header_toString() ;
	}
	m_result = Result::null;
	if (reply.header(Head::App)!=name().toUtf8())
	{
		m_error = Error::ServerError;
		emit errorOccurred(m_error);
		return;
	}
	//错误
	m_error = toError(reply.header(Head::Error));

	if (m_error != Error::NoError)
	{
		emit errorOccurred(m_error);
		if (isDebugModel(Debug::error))
		{
			XQLog(logName()) << "errorOccurred\t" << error_toByteArray(m_error);
		}
	}
	else if (!reply.header(Head::Result).isEmpty())
	{
		resultProcessing(toResult(reply.header(Head::Result)));
	}
	if (--m_requestCount == 0)
		emit done();
}
